home *** CD-ROM | disk | FTP | other *** search
Text File | 2002-06-13 | 23.7 KB | 1,062 lines |
- // Copyright (C) 2001-2002 Raven Software
- //
- // cg_servercmds.c -- reliably sequenced text commands sent by the server
- // these are processed at snapshot transition time, so there will definately
- // be a valid snapshot this frame
-
- #include "cg_local.h"
- #include "../../ui/menudef.h"
- #if !defined(CL_LIGHT_H_INC)
- #include "cg_lights.h"
- #endif
-
- /*
- =================
- CG_ParseScores
- =================
- */
- static void CG_ParseScores( void )
- {
- int i;
-
- cg.scoreBoardSpectators[0] = '\0';
-
- cg.numScores = atoi( CG_Argv( 1 ) );
- if ( cg.numScores > MAX_CLIENTS )
- {
- cg.numScores = MAX_CLIENTS;
- }
-
- cg.teamScores[0] = atoi( CG_Argv( 2 ) );
- cg.teamScores[1] = atoi( CG_Argv( 3 ) );
-
- memset( cg.scores, 0, sizeof( cg.scores ) );
- for ( i = 0 ; i < cg.numScores ; i++ )
- {
- cg.scores[i].client = atoi( CG_Argv( i * 9 + 4 ) );
- cg.scores[i].score = atoi( CG_Argv( i * 9 + 5 ) );
- cg.scores[i].kills = atoi( CG_Argv( i * 9 + 6 ) );
- cg.scores[i].deaths = atoi( CG_Argv( i * 9 + 7 ) );
- cg.scores[i].ping = atoi( CG_Argv( i * 9 + 8 ) );
- cg.scores[i].time = atoi( CG_Argv( i * 9 + 9 ) );
- cgs.clientinfo[ cg.scores[i].client ].ghost = atoi( CG_Argv( i * 9 + 10 ) );
- cgs.clientinfo[ cg.scores[i].client ].gametypeitems = atoi( CG_Argv( i * 9 + 11 ) );
- cg.scores[i].teamkillDamage = atoi( CG_Argv( i * 9 + 12 ) );
-
- if ( cg.scores[i].client < 0 || cg.scores[i].client >= MAX_CLIENTS )
- {
- cg.scores[i].client = 0;
- }
-
- if ( cg.scores[i].ping < 0 )
- {
- cg.scores[i].time = 0;
- }
-
- cgs.clientinfo[ cg.scores[i].client ].score = cg.scores[i].score;
- cg.scores[i].team = cgs.clientinfo[cg.scores[i].client].team;
-
- if ( cg.scores[i].team == TEAM_SPECTATOR )
- {
- if ( cg.scoreBoardSpectators[0] )
- {
- strcat ( cg.scoreBoardSpectators, ", " );
- }
-
- strcat ( cg.scoreBoardSpectators, va("%s (%d)", cgs.clientinfo[cg.scores[i].client].name, cg.scores[i].ping ) );
- }
- }
- }
-
- /*
- ================
- CG_ParseServerinfo
-
- This is called explicitly when the gamestate is first received,
- and whenever the server updates any serverinfo flagged cvars
- ================
- */
- void CG_ParseServerinfo( void )
- {
- const char *info;
- char *mapname;
-
- info = CG_ConfigString( CS_SERVERINFO );
- cgs.gametype = BG_FindGametype ( Info_ValueForKey( info, "g_gametype" ) );
- cgs.gametypeData = &bg_gametypeData[cgs.gametype];
- cgs.dmflags = atoi( Info_ValueForKey( info, "dmflags" ) );
- cgs.teamflags = atoi( Info_ValueForKey( info, "teamflags" ) );
- cgs.scorelimit = atoi( Info_ValueForKey( info, "scorelimit" ) );
- cgs.timelimit = atoi( Info_ValueForKey( info, "timelimit" ) );
- cgs.maxclients = atoi( Info_ValueForKey( info, "sv_maxclients" ) );
- cgs.friendlyFire = atoi( Info_ValueForKey( info, "g_friendlyFire" ) ) ? qtrue : qfalse;
- mapname = Info_ValueForKey( info, "mapname" );
- Com_sprintf( cgs.mapname, sizeof( cgs.mapname ), "maps/%s.bsp", mapname );
-
- trap_Cvar_Set ( "ui_about_gametype", va("%i", cgs.gametype ) );
- trap_Cvar_Set ( "ui_about_gametypename", cgs.gametypeData->displayName );
- trap_Cvar_Set ( "ui_about_scorelimit", va("%i", cgs.scorelimit ) );
- trap_Cvar_Set ( "ui_about_timelimit", va("%i", cgs.timelimit ) );
- trap_Cvar_Set ( "ui_about_maxclients", va("%i", cgs.maxclients ) );
- trap_Cvar_Set ( "ui_about_dmflags", va("%i", cgs.dmflags ) );
- trap_Cvar_Set ( "ui_about_mapname", mapname );
- trap_Cvar_Set ( "ui_about_hostname", Info_ValueForKey( info, "sv_hostname" ) );
- trap_Cvar_Set ( "ui_about_needpass", Info_ValueForKey( info, "g_needpass" ) );
- trap_Cvar_Set ( "ui_about_botminplayers", Info_ValueForKey ( info, "bot_minplayers" ) );
- trap_Cvar_Set ( "ui_info_availableweapons", Info_ValueForKey ( info, "g_availableWeapons" ) );
- trap_Cvar_Set ( "ui_info_teamgame", va("%i", cgs.gametypeData->teams ? 1 : 0 ) );
-
- BG_SetAvailableOutfitting ( Info_ValueForKey ( info, "g_availableWeapons" ) );
-
- if ( cgs.gametypeData->teams )
- {
- trap_Cvar_Set ( "ui_info_redteam", CG_ConfigString ( CS_GAMETYPE_REDTEAM ) );
- trap_Cvar_Set ( "ui_info_blueteam", CG_ConfigString ( CS_GAMETYPE_BLUETEAM ) );
- }
- else
- {
- trap_Cvar_Set ( "ui_info_redteam", "" );
- trap_Cvar_Set ( "ui_info_blueteam", "" );
- }
-
- info = CG_ConfigString( CS_TERRAINS + 1 );
- if ( !info || !*info )
- {
- cg.mInRMG = qfalse;
- }
- else
- {
- cg.mInRMG = qtrue;
- }
- }
-
- /*
- ==================
- CG_ParseWarmup
- ==================
- */
- static void CG_ParseWarmup( void )
- {
- const char *info;
- int warmup;
-
- info = CG_ConfigString( CS_WARMUP );
-
- warmup = atoi( info );
- cg.warmupCount = -1;
-
- cg.warmup = warmup;
- }
-
- static void CG_ParseGametypeTimer ( void )
- {
- cgs.gametypeTimerTime = atoi( CG_ConfigString( CS_GAMETYPE_TIMER ) );
- }
-
- static void CG_ParseGametypeMessage ( void )
- {
- char temp[1024];
- char* comma;
-
- strcpy ( temp, CG_ConfigString( CS_GAMETYPE_MESSAGE ) );
- comma = strchr ( temp, ',' );
- if ( !comma )
- {
- return;
- }
-
- *(comma++) = '\0';
-
- cgs.gametypeMessageTime = atoi ( temp );
-
- // Silent gametype message
- if ( *comma == '@' )
- {
- strcpy ( cgs.gametypeMessage, comma + 1 );
- }
- else
- {
- strcpy ( cgs.gametypeMessage, comma );
- Com_Printf ( "@%s\n", cgs.gametypeMessage );
- }
- }
-
- /*
- ================
- CG_ParseVoteTime
- ================
- */
- static void CG_ParseVoteTime ( void )
- {
- char temp[1024];
- char* comma;
- const char *str;
-
- str = CG_ConfigString( CS_VOTE_TIME );
-
- strcpy ( temp, str );
- comma = strchr ( temp, ',' );
- if ( !comma )
- {
- cgs.voteTime = cgs.voteDuration = 0;
- return;
- }
- *comma = 0;
-
- cgs.voteTime = atoi(str);
- cgs.voteDuration = atoi(comma+1);
- cgs.voteModified = qtrue;
- }
-
- /*
- ================
- CG_SetConfigValues
-
- Called on load to set the initial values from configure strings
- ================
- */
- void CG_SetConfigValues( void )
- {
- int i;
-
- cgs.levelStartTime = atoi( CG_ConfigString( CS_LEVEL_START_TIME ) );
- cg.warmup = atoi( CG_ConfigString( CS_WARMUP ) );
- cgs.pickupsDisabled = atoi( CG_ConfigString( CS_PICKUPSDISABLED ) );
- cgs.gameID = atoi( CG_ConfigString( CS_GAME_ID ) );
-
- trap_Cvar_Set ( "ui_info_pickupsdisabled", va("%i", cgs.pickupsDisabled ) );
-
- CG_ParseGametypeTimer ( );
- CG_ParseGametypeMessage ( );
- CG_ParseVoteTime ( );
-
- for ( i = 0; i < MAX_HUDICONS; i ++ )
- {
- cgs.hudIcons[i] = atoi ( CG_ConfigString ( CS_HUDICONS + i ) );
- }
- }
-
- /*
- =====================
- CG_ShaderStateChanged
- =====================
- */
- void CG_ShaderStateChanged(void) {
- char originalShader[MAX_QPATH];
- char newShader[MAX_QPATH];
- char timeOffset[16];
- const char *o;
- char *n,*t;
-
- o = CG_ConfigString( CS_SHADERSTATE );
- while (o && *o) {
- n = strstr(o, "=");
- if (n && *n) {
- strncpy(originalShader, o, n-o);
- originalShader[n-o] = 0;
- n++;
- t = strstr(n, ":");
- if (t && *t) {
- strncpy(newShader, n, t-n);
- newShader[t-n] = 0;
- } else {
- break;
- }
- t++;
- o = strstr(t, "@");
- if (o) {
- strncpy(timeOffset, t, o-t);
- timeOffset[o-t] = 0;
- o++;
- trap_R_RemapShader( originalShader, newShader, timeOffset );
- }
- } else {
- break;
- }
- }
- }
-
- /*
- ================
- CG_ConfigStringModified
- ================
- */
- static void CG_ConfigStringModified( void )
- {
- const char *str;
- int num;
-
- num = atoi( CG_Argv( 1 ) );
-
- // get the gamestate from the client system, which will have the
- // new configstring already integrated
- trap_GetGameState( &cgs.gameState );
-
- // look up the individual string that was modified
- str = CG_ConfigString( num );
-
- // do something with it if necessary
- if ( num == CS_MUSIC )
- {
- CG_StartMusic( qtrue );
- }
- else if ( num == CS_SERVERINFO )
- {
- CG_ParseServerinfo();
- }
- else if ( num == CS_WARMUP )
- {
- CG_ParseWarmup();
- }
- else if ( num == CS_GAMETYPE_TIMER )
- {
- CG_ParseGametypeTimer ( );
- }
- else if ( num == CS_GAMETYPE_MESSAGE )
- {
- CG_ParseGametypeMessage ( );
- }
- else if ( num == CS_LEVEL_START_TIME )
- {
- cgs.levelStartTime = atoi( str );
- }
- else if ( num == CS_VOTE_TIME )
- {
- CG_ParseVoteTime();
- }
- else if ( num == CS_VOTE_NEEDED )
- {
- cgs.voteNeeded = atoi( str );
- cgs.voteModified = qtrue;
- }
- else if ( num == CS_VOTE_YES )
- {
- cgs.voteYes = atoi( str );
- cgs.voteModified = qtrue;
- }
- else if ( num == CS_VOTE_NO )
- {
- cgs.voteNo = atoi( str );
- cgs.voteModified = qtrue;
- }
- else if ( num == CS_VOTE_STRING )
- {
- Q_strncpyz( cgs.voteString, str, sizeof( cgs.voteString ) );
- trap_S_StartLocalSound( cgs.media.talkSound, CHAN_ANNOUNCER );
- }
- else if ( num == CS_INTERMISSION )
- {
- cg.intermissionStarted = atoi( str );
- }
- else if ( num >= CS_MODELS && num < CS_MODELS+MAX_MODELS )
- {
- cgs.gameModels[ num-CS_MODELS ] = trap_R_RegisterModel( str );
- }
- else if ( num >= CS_SOUNDS && num < CS_SOUNDS+MAX_MODELS )
- {
- if ( str[0] != '*' )
- {
- // player specific sounds don't register here
- cgs.gameSounds[ num-CS_SOUNDS] = trap_S_RegisterSound( str );
- }
- }
- else if ( num >= CS_PLAYERS && num < CS_PLAYERS+MAX_CLIENTS )
- {
- CG_NewClientInfo( num - CS_PLAYERS );
- }
- else if ( num == CS_SHADERSTATE )
- {
- CG_ShaderStateChanged();
- }
- else if ( num >= CS_LIGHT_STYLES && num < CS_LIGHT_STYLES + (MAX_LIGHT_STYLES * 3))
- {
- CG_SetLightstyle(num - CS_LIGHT_STYLES);
- }
- else if ( num >= CS_ICONS && num < CS_ICONS + MAX_ICONS )
- {
- cgs.gameIcons[ num - CS_ICONS ] = trap_R_RegisterShaderNoMip ( str );
- }
- else if ( num >= CS_HUDICONS && num < CS_HUDICONS + MAX_HUDICONS )
- {
- cgs.hudIcons[ num - CS_HUDICONS ] = atoi ( str );
- }
- }
-
-
- /*
- =======================
- CG_AddChatText
-
- Adds chat text to the chat chat buffer
- =======================
- */
- static void CG_AddChatText ( int client, const char *str )
- {
- int len;
- char *p;
- char *ls;
- int lastcolor;
- int chatHeight;
- float w;
-
- if ( client >= 0 )
- {
- cgs.clientinfo[client].mLastChatTime = cg.time;
- }
-
- // Grab the users chat height settings
- chatHeight = cg_chatHeight.integer;
- if ( chatHeight > CHAT_HEIGHT )
- {
- chatHeight = CHAT_HEIGHT;
- }
-
- // Chats disabled?
- if ( chatHeight <= 0 || cg_chatTime.integer <= 0 )
- {
- cgs.chatPos = cgs.chatLastPos = 0;
- return;
- }
-
- len = 0;
-
- lastcolor = COLOR_WHITE;
-
- // Next position to write chat text too in the circular chat buffer
- p = cgs.chatText[cgs.chatPos % chatHeight];
- *p = 0;
-
- ls = NULL;
- w = 0;
-
- while (*str)
- {
- float cw = trap_R_GetTextWidth ( va("%c",*str), cgs.media.hudFont, 0.43f, 0 );
-
- if ( w > 560 )
- {
- w = 0;
-
- if (ls)
- {
- str -= (p - ls);
- str++;
- p -= (p - ls);
- }
-
- *p = 0;
-
- cgs.chatTime[cgs.chatPos % chatHeight] = cg.time;
-
- cgs.chatPos++;
- p = cgs.chatText[ cgs.chatPos % chatHeight ];
- *p = 0;
- *p++ = Q_COLOR_ESCAPE;
- *p++ = lastcolor;
- len = 0;
- ls = NULL;
- }
-
- if ( Q_IsColorString( str ) )
- {
- *p++ = *str++;
- lastcolor = *str;
- *p++ = *str++;
- continue;
- }
-
- if (*str == ' ')
- {
- ls = p;
- }
-
- *p++ = *str++;
- len++;
- w += cw;
- }
- *p = 0;
-
- cgs.chatTime[ cgs.chatPos % chatHeight] = cg.time;
- cgs.chatPos++;
-
- if (cgs.chatPos - cgs.chatLastPos > chatHeight)
- {
- cgs.chatLastPos = cgs.chatPos - chatHeight;
- }
- }
-
- /*
- ===============
- CG_MapRestart
-
- The server has issued a map_restart, so the next snapshot
- is completely new and should not be interpolated to.
-
- A map restart will clear everything, but doesn't
- require a reload of all the media
- ===============
- */
- void CG_MapRestart( qboolean gametypeRestart )
- {
- if ( cg_showmiss.integer )
- {
- Com_Printf( "CG_MapRestart\n" );
- }
-
- trap_R_ClearDecals ( );
- trap_FX_Reset ( );
- trap_MAT_Reset();
-
- CG_InitLocalEntities();
-
- cg.intermissionStarted = qfalse;
-
- // dont clear votes on gametype restarts
- if ( !gametypeRestart )
- {
- cgs.voteTime = 0;
- cgs.gametypeMessage[0] = '\0';
- cgs.gametypeMessageTime = 0;
- }
-
- cgs.gameover[0] = '\0';
-
- cg.mapRestart = qtrue;
-
- // Make sure the weapon selection menu isnt up
- cg.weaponMenuUp = qfalse;
-
- cg.gametypeStarted = qfalse;
-
- // cgs.media.mAutomap = 0; // make sure to re-upload the auto-map
-
- CG_StartMusic(qtrue);
-
- trap_S_ClearLoopingSounds(qtrue);
-
- trap_Cvar_Set("cg_thirdPerson", "0");
- }
-
- #define MAX_VOICEFILESIZE 16384
- #define MAX_VOICEFILES 8
- #define MAX_VOICECHATS 64
- #define MAX_VOICESOUNDS 64
- #define MAX_CHATSIZE 64
- #define MAX_HEADMODELS 64
-
- typedef struct voiceChat_s
- {
- char id[64];
- int numSounds;
- sfxHandle_t sounds[MAX_VOICESOUNDS];
- char chats[MAX_VOICESOUNDS][MAX_CHATSIZE];
- } voiceChat_t;
-
- typedef struct voiceChatList_s
- {
- char name[64];
- int gender;
- int numVoiceChats;
- voiceChat_t voiceChats[MAX_VOICECHATS];
- } voiceChatList_t;
-
- typedef struct headModelVoiceChat_s
- {
- char headmodel[64];
- int voiceChatNum;
- } headModelVoiceChat_t;
-
- voiceChatList_t voiceChatLists[MAX_VOICEFILES];
- headModelVoiceChat_t headModelVoiceChat[MAX_HEADMODELS];
-
- /*
- =================
- CG_ParseVoiceChats
- =================
- */
- int CG_ParseVoiceChats( const char *filename, voiceChatList_t *voiceChatList, int maxVoiceChats ) {
- int len, i;
- fileHandle_t f;
- char buf[MAX_VOICEFILESIZE];
- const char **p, *ptr;
- char *token;
- voiceChat_t *voiceChats;
- qboolean compress;
-
- compress = qtrue;
- if (cg_buildScript.integer) {
- compress = qfalse;
- }
-
- len = trap_FS_FOpenFile( filename, &f, FS_READ );
- if ( !f ) {
- trap_Print( va( S_COLOR_RED "voice chat file not found: %s\n", filename ) );
- return qfalse;
- }
- if ( len >= MAX_VOICEFILESIZE ) {
- trap_Print( va( S_COLOR_RED "voice chat file too large: %s is %i, max allowed is %i", filename, len, MAX_VOICEFILESIZE ) );
- trap_FS_FCloseFile( f );
- return qfalse;
- }
-
- trap_FS_Read( buf, len, f );
- buf[len] = 0;
- trap_FS_FCloseFile( f );
-
- ptr = buf;
- p = &ptr;
-
- Com_sprintf(voiceChatList->name, sizeof(voiceChatList->name), "%s", filename);
- voiceChats = voiceChatList->voiceChats;
- for ( i = 0; i < maxVoiceChats; i++ ) {
- voiceChats[i].id[0] = 0;
- }
- token = COM_ParseExt(p, qtrue);
- if (!token || token[0] == 0) {
- return qtrue;
- }
- if (!Q_stricmp(token, "female")) {
- voiceChatList->gender = GENDER_FEMALE;
- }
- else if (!Q_stricmp(token, "male")) {
- voiceChatList->gender = GENDER_MALE;
- }
- else if (!Q_stricmp(token, "neuter")) {
- voiceChatList->gender = GENDER_NEUTER;
- }
- else {
- trap_Print( va( S_COLOR_RED "expected gender not found in voice chat file: %s\n", filename ) );
- return qfalse;
- }
-
- voiceChatList->numVoiceChats = 0;
- while ( 1 ) {
- token = COM_ParseExt(p, qtrue);
- if (!token || token[0] == 0) {
- return qtrue;
- }
- Com_sprintf(voiceChats[voiceChatList->numVoiceChats].id, sizeof( voiceChats[voiceChatList->numVoiceChats].id ), "%s", token);
- token = COM_ParseExt(p, qtrue);
- if (Q_stricmp(token, "{")) {
- trap_Print( va( S_COLOR_RED "expected { found %s in voice chat file: %s\n", token, filename ) );
- return qfalse;
- }
- voiceChats[voiceChatList->numVoiceChats].numSounds = 0;
- while(1) {
- token = COM_ParseExt(p, qtrue);
- if (!token || token[0] == 0) {
- return qtrue;
- }
- if (!Q_stricmp(token, "}"))
- break;
- voiceChats[voiceChatList->numVoiceChats].sounds[voiceChats[voiceChatList->numVoiceChats].numSounds] =
- trap_S_RegisterSound( token );
- token = COM_ParseExt(p, qtrue);
- if (!token || token[0] == 0) {
- return qtrue;
- }
- Com_sprintf(voiceChats[voiceChatList->numVoiceChats].chats[
- voiceChats[voiceChatList->numVoiceChats].numSounds], MAX_CHATSIZE, "%s", token);
- voiceChats[voiceChatList->numVoiceChats].numSounds++;
- if (voiceChats[voiceChatList->numVoiceChats].numSounds >= MAX_VOICESOUNDS)
- break;
- }
- voiceChatList->numVoiceChats++;
- if (voiceChatList->numVoiceChats >= maxVoiceChats)
- return qtrue;
- }
- return qtrue;
- }
-
- /*
- =================
- CG_LoadVoiceChats
- =================
- */
- void CG_LoadVoiceChats( void )
- {
- int size;
-
- size = trap_MemoryRemaining();
- CG_ParseVoiceChats( "scripts/female1.voice", &voiceChatLists[0], MAX_VOICECHATS );
- CG_ParseVoiceChats( "scripts/male1.voice", &voiceChatLists[1], MAX_VOICECHATS );
- }
-
- /*
- =================
- CG_GetVoiceChat
- =================
- */
- int CG_GetVoiceChat( voiceChatList_t *voiceChatList, const char *id, sfxHandle_t *snd, char **chat)
- {
- int i, rnd;
-
- for ( i = 0; i < voiceChatList->numVoiceChats; i++ )
- {
- if ( !Q_stricmp( id, voiceChatList->voiceChats[i].id ) )
- {
- rnd = random() * voiceChatList->voiceChats[i].numSounds;
- *snd = voiceChatList->voiceChats[i].sounds[rnd];
- *chat = voiceChatList->voiceChats[i].chats[rnd];
- return qtrue;
- }
- }
-
- return qfalse;
- }
-
- /*
- =================
- CG_VoiceChatListForClient
- =================
- */
- voiceChatList_t *CG_VoiceChatListForClient( int clientNum )
- {
- clientInfo_t *ci;
-
- ci = &cgs.clientinfo[ clientNum ];
-
- switch ( ci->gender )
- {
- case GENDER_FEMALE:
- return &voiceChatLists[0];
-
- case GENDER_MALE:
- return &voiceChatLists[1];
- }
-
- // just return the male voice chat list since there are more male characters
- return &voiceChatLists[1];
- }
-
- #define MAX_VOICECHATBUFFER 32
-
- typedef struct bufferedVoiceChat_s
- {
- int clientNum;
- sfxHandle_t snd;
- int voiceOnly;
- char cmd[MAX_SAY_TEXT];
- char message[MAX_SAY_TEXT];
- } bufferedVoiceChat_t;
-
- bufferedVoiceChat_t voiceChatBuffer[MAX_VOICECHATBUFFER];
-
- /*
- =================
- CG_PlayVoiceChat
- =================
- */
- void CG_PlayVoiceChat( bufferedVoiceChat_t *vchat )
- {
- // if we are going into the intermission, don't start any voices
- if ( cg.intermissionStarted )
- {
- return;
- }
-
- if ( cg_voiceRadio.integer )
- {
- trap_S_StartLocalSound( vchat->snd, CHAN_VOICE);
- }
-
- if (!vchat->voiceOnly && !cg_noVoiceText.integer)
- {
- CG_AddChatText ( vchat->clientNum, vchat->message );
- }
-
- voiceChatBuffer[cg.voiceChatBufferOut].snd = 0;
- }
-
- /*
- =====================
- CG_PlayBufferedVoieChats
- =====================
- */
- void CG_PlayBufferedVoiceChats( void )
- {
- if ( cg.voiceChatTime < cg.time )
- {
- if (cg.voiceChatBufferOut != cg.voiceChatBufferIn && voiceChatBuffer[cg.voiceChatBufferOut].snd)
- {
- //
- CG_PlayVoiceChat(&voiceChatBuffer[cg.voiceChatBufferOut]);
- //
- cg.voiceChatBufferOut = (cg.voiceChatBufferOut + 1) % MAX_VOICECHATBUFFER;
- cg.voiceChatTime = cg.time + 1000;
- }
- }
- }
-
- /*
- =====================
- CG_AddBufferedVoiceChat
- =====================
- */
- void CG_AddBufferedVoiceChat( bufferedVoiceChat_t *vchat )
- {
- // if we are going into the intermission, don't start any voices
- if ( cg.intermissionStarted )
- {
- return;
- }
-
- memcpy(&voiceChatBuffer[cg.voiceChatBufferIn], vchat, sizeof(bufferedVoiceChat_t));
- cg.voiceChatBufferIn = (cg.voiceChatBufferIn + 1) % MAX_VOICECHATBUFFER;
- if (cg.voiceChatBufferIn == cg.voiceChatBufferOut)
- {
- CG_PlayVoiceChat( &voiceChatBuffer[cg.voiceChatBufferOut] );
- cg.voiceChatBufferOut++;
- }
- }
-
- /*
- =================
- CG_VoiceChatLocal
- =================
- */
- void CG_VoiceChatLocal( qboolean voiceOnly, int clientNum, const char* chatprefix, const char *cmd )
- {
- char *chat;
- voiceChatList_t *voiceChatList;
- sfxHandle_t snd;
- bufferedVoiceChat_t vchat;
-
- // if we are going into the intermission, don't start any voices
- if ( cg.intermissionStarted )
- {
- return;
- }
-
- // Get the voice chat info for the speaking client
- voiceChatList = CG_VoiceChatListForClient( clientNum );
- if ( !CG_GetVoiceChat( voiceChatList, cmd, &snd, &chat ) )
- {
- return;
- }
-
- vchat.clientNum = clientNum;
- vchat.snd = snd;
- vchat.voiceOnly = voiceOnly;
- Q_strncpyz(vchat.cmd, cmd, sizeof(vchat.cmd));
-
- Com_sprintf ( vchat.message, sizeof(vchat.message), "%s%s", chatprefix, chat );
-
- CG_AddBufferedVoiceChat(&vchat);
- }
-
- /*
- =================
- CG_VoiceChat
- =================
- */
- void CG_VoiceChat( int mode )
- {
- char cmd[MAX_QPATH];
- const char *chatprefix;
- qboolean voiceOnly;
- int clientNum;
-
- voiceOnly = atoi(CG_Argv(1));
- clientNum = atoi(CG_Argv(2));
- Com_sprintf ( cmd, MAX_QPATH, CG_Argv(4) );
- chatprefix = CG_Argv(3);
-
- CG_VoiceChatLocal ( voiceOnly, clientNum, chatprefix, cmd );
- }
-
- /*
- =================
- CG_RemoveChatEscapeChar
- =================
- */
- static void CG_RemoveChatEscapeChar( char *text ) {
- int i, l;
-
- l = 0;
- for ( i = 0; text[i]; i++ ) {
- if (text[i] == '\x19')
- continue;
- text[l++] = text[i];
- }
- text[l] = '\0';
- }
-
- /*
- =================
- CG_ServerCommand
-
- The string has been tokenized and can be retrieved with
- Cmd_Argc() / Cmd_Argv()
- =================
- */
- static void CG_ServerCommand( void ) {
- const char *cmd;
- char text[MAX_SAY_TEXT];
-
- cmd = CG_Argv(0);
-
- if ( !cmd[0] ) {
- // server claimed the command
- return;
- }
-
- if ( !strcmp( cmd, "cp" ) )
- {
- const char* s;
-
- s = CG_Argv(1);
- if ( *s == '@' )
- {
- s++;
- }
- else
- {
- Com_Printf ( "@%s", s );
- }
-
- CG_CenterPrint( s, 0.43f );
- return;
- }
-
- if ( !strcmp( cmd, "cs" ) )
- {
- CG_ConfigStringModified();
- return;
- }
-
- if ( !strcmp( cmd, "print" ) )
- {
- Com_Printf( "%s", CG_Argv(1) );
-
- /*
- cmd = CG_Argv(1); // yes, this is obviously a hack, but so is the way we hear about
- // votes passing or failing
- if ( !Q_stricmpn( cmd, "vote failed", 11 ) )
- {
- trap_S_StartLocalSound( cgs.media.voteFailed, CHAN_ANNOUNCER );
- }
- else if ( !Q_stricmpn( cmd, "vote passed", 11 ) )
- {
- trap_S_StartLocalSound( cgs.media.votePassed, CHAN_ANNOUNCER );
- }
- */
- return;
- }
-
- if ( !strcmp( cmd, "chat" ) )
- {
- if ( !cg_teamChatsOnly.integer )
- {
- trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND );
- Q_strncpyz( text, CG_Argv(2), MAX_SAY_TEXT );
- CG_RemoveChatEscapeChar( text );
- CG_AddChatText ( atoi(CG_Argv(1)), text );
- Com_Printf( "@%s\n", text );
- }
- return;
- }
-
- if ( !strcmp( cmd, "tchat" ) )
- {
- trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND );
- Q_strncpyz( text, CG_Argv(2), MAX_SAY_TEXT );
- CG_RemoveChatEscapeChar( text );
- CG_AddChatText ( atoi(CG_Argv(1)), text );
- Com_Printf( "@%s\n", text );
- return;
- }
-
- if ( !strcmp( cmd, "vglobal" ) )
- {
- char *chat;
- voiceChatList_t *voiceChatList;
- sfxHandle_t snd;
- int clientNum;
-
- if ( !cg_voiceGlobal.integer )
- {
- return;
- }
-
- clientNum = atoi(CG_Argv(1));
-
- // Get the voice chat info for the speaking client
- voiceChatList = CG_VoiceChatListForClient( clientNum );
- if ( !CG_GetVoiceChat( voiceChatList, CG_Argv(2), &snd, &chat ) )
- {
- return;
- }
-
- trap_S_StartSound ( NULL, clientNum, CHAN_AUTO, snd, 240, 1150 );
- return;
- }
-
- if ( !strcmp( cmd, "vtchat" ) )
- {
- CG_VoiceChat( SAY_TEAM );
- return;
- }
-
- if ( !strcmp( cmd, "vtell" ) )
- {
- CG_VoiceChat( SAY_TELL );
- return;
- }
-
- if ( !strcmp( cmd, "scores" ) )
- {
- CG_ParseScores();
- CG_UpdateTeamCountCvars ( );
- return;
- }
-
- if ( !strcmp( cmd, "map_restart" ) )
- {
- CG_MapRestart( qfalse );
- return;
- }
-
- if ( Q_stricmp (cmd, "remapShader") == 0 )
- {
- if (trap_Argc() == 4)
- {
- trap_R_RemapShader(CG_Argv(1), CG_Argv(2), CG_Argv(3));
- }
- }
-
- // loaddeferred can be both a servercmd and a consolecmd
- if ( !strcmp( cmd, "loaddeferred" ) )
- {
- CG_LoadDeferredPlayers();
- return;
- }
-
- // clientLevelShot is sent before taking a special screenshot for
- // the menu system during development
- if ( !strcmp( cmd, "clientLevelShot" ) )
- {
- cg.levelShot = qtrue;
- return;
- }
-
- Com_Printf( "Unknown client game command: %s\n", cmd );
- }
-
-
- /*
- ====================
- CG_ExecuteNewServerCommands
-
- Execute all of the server commands that were received along
- with this this snapshot.
- ====================
- */
- void CG_ExecuteNewServerCommands( int latestSequence ) {
- while ( cgs.serverCommandSequence < latestSequence ) {
- if ( trap_GetServerCommand( ++cgs.serverCommandSequence ) ) {
- CG_ServerCommand();
- }
- }
- }
-